/**
 * @file    gt98xx_drv_uart.c
 * @author  Giantec-Semi ATE
 * @brief   Source file of UART driver module.
 * @version 0.1
 * 
 * @copyright Copyright (c) 2021 Giantec-Semi
 */

#include "gt98xx_drv_uart.h"

/**
 * @addtogroup GT98xx_DRV
 * @{
 */

/**
 * @addtogroup UART_DRV
 * @{
 */

/**
 * @addtogroup UART_DRV_Private_Macros
 * @{
 */

/**
 * @def IS_DRV_UART_PARITY
 * @brief Check if __VALUE__ is UART Parity type
 */
#define IS_DRV_UART_PARITY(__VALUE__)     (((__VALUE__) == DRV_UART_PARITY_NONE) || \
                                           ((__VALUE__) == DRV_UART_PARITY_ODD) || \
                                           ((__VALUE__) == DRV_UART_PARITY_EVEN))

/**
 * @def IS_DRV_UART_DATAWIDTH
 * @brief Check if __VALUE__ is UART DataWidth type
 */
#define IS_DRV_UART_DATAWIDTH(__VALUE__)  (((__VALUE__) == DRV_UART_DATAWIDTH_5B) || \
                                           ((__VALUE__) == DRV_UART_DATAWIDTH_6B) || \
                                           ((__VALUE__) == DRV_UART_DATAWIDTH_7B) || \
                                           ((__VALUE__) == DRV_UART_DATAWIDTH_8B))

/**
 * @def IS_DRV_UART_STOPBITS
 * @brief Check if __VALUE__ is UART StopBits type
 */
#define IS_DRV_UART_STOPBITS(__VALUE__)   (((__VALUE__) == DRV_UART_STOPBITS_1) || \
                                           ((__VALUE__) == DRV_UART_STOPBITS_1_5) || \
                                           ((__VALUE__) == DRV_UART_STOPBITS_2))

/** @} UART_DRV_Private_Macros */

/**
 * @addtogroup UART_DRV_Exported_Functions
 * @{
 */

/**
 * @addtogroup UART_DRV_EF_Init
 * @{
 */

/**
 * @fn ErrorStatus DrvUartDeInit(UartTypedef* uart_instance)
 * @brief De-initialize UART registers
 * 
 * @param[in] uart_instance UART instance
 * @return UART is de-initialized or not
 * @retval kSuccess UART registers are de-initialized
 * @retval kError UART registers are not de-initialized
 */
ErrorStatus DrvUartDeInit(UartTypedef* uart_instance) {
  ErrorStatus status = kSuccess;

  assert_param(IS_UART_INSTANCE(uart_instance));
  if (UART == uart_instance) {
    CLEAR_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_UART);
    SET_BIT(RST_CTL_REG->MCU_BLK_RST, MCU_BLK_RST_UART);
  } else {
    status = kError;
  }
  return status;
}

/**
 * @fn ErrorStatus DrvUartInit(UartTypedef* uart_instance, DrvUartInitTypedef* uart_init_struct)
 * @brief Initialize UART registers according to the specified parameters in UART_InitStruct
 * 
 * @param[in] uart_instance UART instance
 * @param[in] uart_init_struct pointer to a DrvUartInitTypedef structure that contians the 
 *            configuration information for the specified UART peripheral 
 * @return UART is initialized or not
 * @retval kSuccess UART registers are initialized according to uart_init_struct content
 * @retval kError Problem occured during UART registers initialization
 */
ErrorStatus DrvUartInit(UartTypedef* uart_instance, DrvUartInitTypedef* uart_init_struct) {
  ErrorStatus status = kError;

  /* Check the parameters */
  assert_param(IS_UART_INSTANCE(uart_instance));
  assert_param(IS_DRV_UART_DATAWIDTH(uart_init_struct->data_width));
  assert_param(IS_DRV_UART_PARITY(uart_init_struct->parity));
  assert_param(IS_DRV_UART_STOPBITS(uart_init_struct->stop_bits));

  if (uart_init_struct->baud_rate) {
    /* Set Baud Rate */
    DrvUartSetBaudRate(uart_instance, uart_init_struct->baud_rate);
    /* UART LCR Configuration */
    MODIFY_REG(uart_instance->LCR,
              (UART_LCR_DLS | UART_LCR_STOP | UART_LCR_PEN | UART_LCR_EPS),
              (uart_init_struct->data_width | uart_init_struct->parity | uart_init_struct->stop_bits));
    status = kSuccess;
  }

  return status;
}

/**
 * @fn void DrvUartStructInit(DrvUartInitTypedef* uart_init_struct)
 * @brief Set each @ref DrvUartInitTypedef field to default value
 * 
 * @param[out] uart_init_struct pointer to a @ref DrvUartInitTypedef structure
 *             whose field will be set to default values
 * @return None
 */
void DrvUartStructInit(DrvUartInitTypedef* uart_init_struct) {
  uart_init_struct->baud_rate  = 19200U;
  uart_init_struct->data_width = DRV_UART_DATAWIDTH_8B;
  uart_init_struct->parity     = DRV_UART_PARITY_NONE;
  uart_init_struct->stop_bits  = DRV_UART_STOPBITS_1;
}


void Uart_SendByte(uint8_t date)
{
  WRITE_REG(UART->RBR_THR_DLL, date);
  while (!READ_BIT(UART->LSR, UART_LSR_THRE));
}



void Uart_SendChar(char volatile *str)
{
	while(*str)
	{
		WRITE_REG(UART->RBR_THR_DLL, *str++);
    while (!READ_BIT(UART->LSR, UART_LSR_THRE));
	}	
}

void Uart_SendString(uint8_t volatile *str)
{
	while(*str)
	{
		WRITE_REG(UART->RBR_THR_DLL, *str++);
    while (!READ_BIT(UART->LSR, UART_LSR_THRE));
	}	
}

void Uart_SendHex8(uint8_t date)
{
	uint8_t buf[5];
	uint8_t tp;
	
	buf[0] = '0';
	buf[1] = 'x';
	tp = (date>>4) & 0x0F;
	if(tp <= 9)
		buf[2] = tp + '0';
	else
	{
		tp -= 0x0A;
		buf[2] = tp + 'A';
	}
	tp = date & 0x0F;
	if(tp <= 9)
		buf[3] = tp + '0';
	else
	{
		tp -= 0x0A;
		buf[3] = tp + 'A';
	}
	buf[4] = 0;
	Uart_SendString(buf);
}

void Uart_SendHex16(uint16_t date)
{
	uint8_t buf[7];
	uint8_t tp, valu;
	
	buf[0] = '0';
	buf[1] = 'x';
	
	valu = (date>>8) & 0x00FF;
	tp = (valu>>4) & 0x0F;
	if(tp <= 9)
		buf[2] = tp + '0';
	else
	{
		tp -= 0x0A;
		buf[2] = tp + 'A';
	}
	tp = valu & 0x0F;
	if(tp <= 9)
		buf[3] = tp + '0';
	else
	{
		tp -= 0x0A;
		buf[3] = tp + 'A';
	}
	
	valu = date & 0x00FF;
	tp = (valu>>4) & 0x0F;
	if(tp <= 9)
		buf[4] = tp + '0';
	else
	{
		tp -= 0x0A;
		buf[4] = tp + 'A';
	}
	tp = valu & 0x0F;
	if(tp <= 9)
		buf[5] = tp + '0';
	else
	{
		tp -= 0x0A;
		buf[5] = tp + 'A';
	}
	
	buf[6] = 0;
	Uart_SendString(buf);
}

void Uart_SendHex32(uint32_t date)
{
	uint8_t buf[11];
	uint8_t tp, valu, i, step;
	
	step = 0;
	buf[step++] = '0';
	buf[step++] = 'x';
	for(i=0; i<4; i++)
	{
		valu = (uint8_t)((date>>(24-(i*8))) & 0x000000FF);
		tp = (valu>>4) & 0x0F;
		if(tp <= 9)
		buf[step++] = tp + '0';
		else
		{
			tp -= 0x0A;
			buf[step++] = tp + 'A';
		}
		tp = valu & 0x0F;
		if(tp <= 9)
			buf[step++] = tp + '0';
		else
		{
			tp -= 0x0A;
			buf[step++] = tp + 'A';
		}
	}
	buf[step] = 0;
	Uart_SendString(buf);
}

void Usart_SendNum_Int32t(int32_t num)
{
	uint8_t buf[20];
	uint8_t step, totl;
	uint32_t valu, tp32;
	
	if(num == 0)
	{
		buf[0] = '0';
		buf[1] = 0;
		Uart_SendString(buf);
		return;
	}
	step = 0;
	if(num < 0)
	{
		buf[step++] = '-';
		valu = (uint32_t)(num * -1);
	}
	else
		valu = (uint32_t)num;
	totl = 0;
	tp32 = valu;
	while(tp32)
	{
		tp32 /= 10;
		totl++;
	}
	buf[totl+step] = 0;
	buf[(totl-1)+step] = (valu % 10) + '0';
	valu /= 10;
	while(--totl)
	{
		buf[(totl-1)+step] = (valu % 10) + '0';
		valu /= 10;
	}
	Uart_SendString(buf);
}

void Usart_SendNum_Int16t(int16_t num)
{
	uint8_t buf[10];
	uint8_t step, totl;
	uint16_t valu, tp16;
	
	if(num == 0)
	{
		buf[0] = '0';
		buf[1] = 0;
		Uart_SendString(buf);
		return;
	}
	step = 0;
	if(num < 0)
	{
		buf[step++] = '-';
		valu = (uint16_t)(num * -1);
	}
	else
		valu = (uint16_t)num;
	totl = 0;
	tp16 = valu;
	while(tp16)
	{
		tp16 /= 10;
		totl++;
	}
	buf[totl+step] = 0;
	buf[(totl-1)+step] = (valu % 10) + '0';
	valu /= 10;
	while(--totl)
	{
		buf[(totl-1)+step] = (valu % 10) + '0';
		valu /= 10;
	}
	Uart_SendString(buf);
}

void Uart_SendFloat(float num, uint8_t dig)
{
  uint8_t i;
	uint8_t data[4];
  uint32_t valu;
  
if(num < 0)
  {
    Uart_SendByte('-');
    num *= -1;
  }
  valu = num;
  Usart_SendNum_Int32t(valu); //inter part
	Uart_SendByte('.');
  num -= valu;								//-int,.XXX
	valu = num*10000;
	 data[0] = valu/1000 + 48;
	 data[1] = valu/100%10 + 48;
	 data[2] = valu/10%10 + 48;
	 data[3] = valu%10 + 48;
	 //Uart_SendString(data);
		Uart_SendByte(data[0]);
	Uart_SendByte(data[1]);
	Uart_SendByte(data[2]);
	Uart_SendByte(data[3]);
  //Usart_SendNum_Int32t(valu);   
}

void SmaSendData(uint32_t *buf,uint8_t ChannelNum)
{
    uint8_t N;
    for(N=0;N < ChannelNum;N++)
 {
    Uart_SendHex32(buf[N]);
    Uart_SendChar("\r\n");
  }
}

/** @} UART_DRV_EF_Init */
/** @} UART_DRV_Exported_Functions */
/** @} UART_DRV */
/** @} GT98xx_DRV */
